﻿#include "GameTimer.h"
#include <windows.h>

GameTimer::GameTimer()
    : mSecondsPerCount(0.0)
    , mDeltaTime(-1.0)
    , mBaseTime(0)
    , mPausedTime(0)
    , mPrevTime(0)
    , mCurTime(0)
    , bStopped(false)
{
    __int64 CountsPerSecond;
    QueryPerformanceFrequency((LARGE_INTEGER*)&CountsPerSecond);
    mSecondsPerCount = 1.0 / CountsPerSecond;
}

// 返回调用Reset()之后经过的总时间，不计入暂停的时间
float GameTimer::TotalTime() const
{
    // If we are stopped, do not count the time that has passed since we stopped.
    // Moreover, if we previously already had a pause, the distance 
    // mStopTime - mBaseTime includes paused time, which we do not want to count.
    // To correct this, we can subtract the paused time from mStopTime:  
    //
    //                     |<--paused time-->|
    // ----*---------------*-----------------*------------*------------*------> time
    //  mBaseTime       mStopTime        startTime     mStopTime    mCurrTime

    if (bStopped)
    {
        return (float)((mStopTime - mPausedTime - mBaseTime) * mSecondsPerCount);
    }

    // The distance mCurrTime - mBaseTime includes paused time,
    // which we do not want to count.  To correct this, we can subtract 
    // the paused time from mCurrTime:  
    //
    //  (mCurTime - mPausedTime) - mBaseTime 
    //
    //                     |<--paused time-->|
    // ----*---------------*-----------------*------------*------> time
    //  mBaseTime       mStopTime        startTime     mCurrTime

    return (float)((mCurTime - mPausedTime - mBaseTime) * mSecondsPerCount);
}

float GameTimer::DeltaTime() const
{
    return (float)mDeltaTime;
}

void GameTimer::Reset()
{
    __int64 CurTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&CurTime);

    mBaseTime = CurTime;
    mPrevTime = CurTime;
    mStopTime = 0;
    bStopped = false;
}

void GameTimer::Start()
{
    __int64 StartTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&StartTime);

    // Accumulate the time elapsed between stop and start pairs.
    //
    //                     |<-------d------->|
    // ----*---------------*-----------------*------------> time
    //  mBaseTime       mStopTime        startTime

    if (bStopped)
    {
        mPausedTime += StartTime - mStopTime;

        mPrevTime = StartTime;
        mStopTime = 0;
        bStopped = false;
    }
}

void GameTimer::Stop()
{
    if (!bStopped)
    {
        __int64 CurTime;
        QueryPerformanceCounter((LARGE_INTEGER*)&CurTime);

        mStopTime = CurTime;
        bStopped = true;
    }
}

void GameTimer::Tick()
{
    if (bStopped)
    {
        mDeltaTime = 0.0;
        return;
    }

    // 获得本帧开始显示的时刻
    __int64 CurTime;
    QueryPerformanceCounter((LARGE_INTEGER*)&CurTime);
    mCurTime = CurTime;

    // 本帧与前一帧的时间差
    mDeltaTime = (mCurTime - mPrevTime) * mSecondsPerCount;

    // 准备计算本帧与下一帧的时间差
    mPrevTime = mCurTime;

    // 使时间差为非负值。
    if (mDeltaTime < 0.0)
    {
        mDeltaTime = 0.0;
    }
}
